package cn.iocoder.boot.springai001.service;

import cn.hutool.core.util.IdUtil;
import cn.iocoder.boot.springai001.entity.ChatSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.messages.Message;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 会话管理服务（内存版本）
 * <p>
 * 提供更好的会话查询和管理功能
 * <p>
 * 使用内存存储会话信息（ConcurrentHashMap）
 * <p>
 * 配置：
 * session.storage.type=memory（默认）
 * <p>
 * 改进点：
 * 1. 使用独立的会话实体
 * 2. 支持多种查询方式
 * 3. 可切换到数据库版本（SessionServiceJpa）
 */
@Slf4j
@Service
@org.springframework.boot.autoconfigure.condition.ConditionalOnProperty(
        name = "session.storage.type",
        havingValue = "memory",
        matchIfMissing = true  // 默认使用内存模式
)
public class SessionService implements ISessionService {

    private final ChatMemory chatMemory;

    // 会话存储：sessionId -> ChatSession
    // 生产环境应该用数据库（如 MySQL, PostgreSQL）
    private final Map<String, ChatSession> sessions = new ConcurrentHashMap<>();

    // 索引：userId -> List<sessionId>
    // 便于快速查询用户的所有会话
    private final Map<String, List<String>> userSessionIndex = new ConcurrentHashMap<>();

    public SessionService(ChatMemory chatMemory) {
        this.chatMemory = chatMemory;
        log.info("✅ 使用内存存储会话信息（ConcurrentHashMap）- 适合开发环境");
        log.warn("⚠️  生产环境建议配置 session.storage.type=database 使用数据库存储");
    }

    /**
     * 创建新会话
     */
    public ChatSession createSession(String userId, String sessionName, String sessionType) {
        String sessionId = IdUtil.simpleUUID();

        ChatSession session = ChatSession.builder()
                .sessionId(sessionId)
                .userId(userId)
                .sessionName(sessionName)
                .conversationId(sessionId)
                .sessionType(sessionType)
                .createdAt(LocalDateTime.now())
                .lastActiveAt(LocalDateTime.now())
                .pinned(false)
                .build();

        // 保存会话
        sessions.put(sessionId, session);

        // 更新用户索引
        userSessionIndex.computeIfAbsent(userId, k -> new ArrayList<>()).add(sessionId);

        log.info("创建会话成功 - 用户: {}, 会话: {}, 名称: {}", userId, sessionId, sessionName);

        return session;
    }

    /**
     * 根据 sessionId 获取会话
     */
    public Optional<ChatSession> getSession(String sessionId) {
        return Optional.ofNullable(sessions.get(sessionId));
    }

    /**
     * 根据 userId 获取所有会话（便于查询）✅
     */
    public List<ChatSession> getUserSessions(String userId) {
        List<String> sessionIds = userSessionIndex.getOrDefault(userId, Collections.emptyList());

        return sessionIds.stream()
                .map(sessions::get)
                .filter(Objects::nonNull)
                .sorted(Comparator.comparing(ChatSession::getLastActiveAt).reversed())
                .collect(Collectors.toList());
    }

    /**
     * 根据 sessionType 获取会话（按场景查询）✅
     */
    public List<ChatSession> getSessionsByType(String userId, String sessionType) {
        return getUserSessions(userId).stream()
                .filter(s -> sessionType.equals(s.getSessionType()))
                .collect(Collectors.toList());
    }

    /**
     * 更新会话最后活跃时间
     */
    public void updateLastActive(String sessionId) {
        ChatSession session = sessions.get(sessionId);
        if (session != null) {
            session.setLastActiveAt(LocalDateTime.now());
        }
    }

    /**
     * 获取会话的消息数量
     */
    public int getMessageCount(String sessionId) {
        return chatMemory.get(sessionId).size();
    }

    /**
     * 获取会话的聊天记录
     *
     * @param sessionId 会话ID
     * @param limit     返回的最大消息数量
     * @return 消息列表
     */
    public List<Message> getSessionMessages(String sessionId, int limit) {
        ChatSession session = sessions.get(sessionId);
        if (session == null) {
            log.warn("会话不存在: {}", sessionId);
            return Collections.emptyList();
        }

        return chatMemory.get(session.getConversationId());
    }

    /**
     * 获取会话的所有聊天记录
     */
    public List<Message> getSessionMessages(String sessionId) {
        return getSessionMessages(sessionId, Integer.MAX_VALUE);
    }

    /**
     * 清空会话历史
     */
    public void clearSessionHistory(String sessionId) {
        ChatSession session = sessions.get(sessionId);
        if (session != null) {
            chatMemory.clear(session.getConversationId());
            log.info("清空会话历史: {}", sessionId);
        }
    }

    /**
     * 删除会话
     */
    public boolean deleteSession(String userId, String sessionId) {
        ChatSession session = sessions.get(sessionId);
        if (session == null || !userId.equals(session.getUserId())) {
            log.warn("会话不存在或用户不匹配: {}", sessionId);
            return false;
        }

        // 清空聊天记忆
        chatMemory.clear(session.getConversationId());

        // 从索引中移除
        List<String> userSessionList = userSessionIndex.get(userId);
        if (userSessionList != null) {
            userSessionList.remove(sessionId);
        }

        // 删除会话
        sessions.remove(sessionId);

        log.info("删除会话成功 - 用户: {}, 会话: {}", userId, sessionId);
        return true;
    }

    /**
     * 置顶会话
     */
    public void pinSession(String sessionId, boolean pinned) {
        ChatSession session = sessions.get(sessionId);
        if (session != null) {
            session.setPinned(pinned);
        }
    }

    /**
     * 搜索会话（按名称）
     */
    public List<ChatSession> searchSessions(String userId, String keyword) {
        return getUserSessions(userId).stream()
                .filter(s -> s.getSessionName().contains(keyword))
                .collect(Collectors.toList());
    }

    /**
     * 获取活跃会话（最近使用的）
     */
    public List<ChatSession> getRecentActiveSessions(String userId, int limit) {
        return getUserSessions(userId).stream()
                .sorted(Comparator.comparing(ChatSession::getLastActiveAt).reversed())
                .limit(limit)
                .collect(Collectors.toList());
    }

    /**
     * 统计信息
     */
    public Map<String, Object> getUserStatistics(String userId) {
        List<ChatSession> userSessions = getUserSessions(userId);

        int totalMessages = userSessions.stream()
                .mapToInt(s -> getMessageCount(s.getConversationId()))
                .sum();

        Map<String, Long> typeCount = userSessions.stream()
                .collect(Collectors.groupingBy(
                        ChatSession::getSessionType,
                        Collectors.counting()
                ));

        return Map.of(
                "totalSessions", userSessions.size(),
                "totalMessages", totalMessages,
                "sessionsByType", typeCount,
                "activeSessionsLast7Days", getActiveSessionsCount(userId, 7)
        );
    }

    private long getActiveSessionsCount(String userId, int days) {
        LocalDateTime threshold = LocalDateTime.now().minusDays(days);
        return getUserSessions(userId).stream()
                .filter(s -> s.getLastActiveAt().isAfter(threshold))
                .count();
    }

    /**
     * 根据 conversationId 获取或创建会话
     * <p>
     * 自动会话管理：如果会话已存在则更新活跃时间，不存在则自动创建
     */
    @Override
    public ChatSession getOrCreateSession(String sessionId, String userId) {
        // 先尝试获取现有会话
        ChatSession existingSession = sessions.get(sessionId);
        
        if (existingSession != null) {
            // 会话已存在，更新最后活跃时间
            existingSession.setLastActiveAt(LocalDateTime.now());
            log.debug("使用现有会话 - conversationId: {}, userId: {}", sessionId, userId);
            return existingSession;
        }

        // 会话不存在，自动创建新会话
        ChatSession newSession = ChatSession.builder()
                .sessionId(sessionId)
                .userId(userId)
                .sessionName("自动会话-" + LocalDateTime.now().toString().substring(0, 19))
                .conversationId(sessionId)
                .sessionType("general")
                .createdAt(LocalDateTime.now())
                .lastActiveAt(LocalDateTime.now())
                .pinned(false)
                .build();

        // 保存会话
        sessions.put(sessionId, newSession);

        // 更新用户索引
        userSessionIndex.computeIfAbsent(userId, k -> new ArrayList<>()).add(sessionId);

        log.info("自动创建会话 - conversationId: {}, userId: {}, 名称: {}",
                sessionId, userId, newSession.getSessionName());

        return newSession;
    }
}

